package com.swsm.utils;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * 线程池
 */
public class ThreadPool {
	
	private int minThreads;
	private int maxThreads;
	private int runCount;
	private final List<PooledThread> threads;
	final LinkedList<Runnable> queue;
	private static final int MIN_THREAD_COUNT = 30;
	private static final int MAX_THREAD_COUNT = 100;
	private static final ThreadPool pool = new ThreadPool(MIN_THREAD_COUNT, MAX_THREAD_COUNT);
	private static final Log log = LogFactory.getLog(ThreadPool.class);

	public ThreadPool(int minThreads, int maxThreads) {
		this.minThreads = minThreads;
		this.maxThreads = maxThreads;
		queue = new LinkedList<Runnable>();
		threads = new ArrayList<PooledThread>(minThreads);
		for (int i = 0; i < minThreads; i++) {
			PooledThread thread = new PooledThread();
			threads.add(thread);
			thread.start();
		}
	}

	public static ThreadPool getDefaultThreadPool() {
		return pool;
	}

	public static void setPoolSize(int minThreads, int maxThreads) {
		pool.minThreads = minThreads;
		pool.maxThreads = maxThreads;
	}

	public void setInstancePoolSize(int minThreads, int maxThreads) {
		this.minThreads = minThreads;
		this.maxThreads = maxThreads;
	}

	public static void processTask(Runnable r) {
		pool.execute(r);
	}

	public static int getRunningPoolSize() {
		return pool.runCount;
	}

	public static int getPoolSize() {
		return pool.threads.size();
	}

	public static int getMaxPoolSize() {
		return pool.maxThreads;
	}

	public static int getMinPoolSize() {
		return pool.minThreads;
	}

	public static int getWorkerQueueSize() {
		return pool.queue.size();
	}

	public int runningPoolSize() {
		return runCount;
	}

	public int poolSize() {
		return threads.size();
	}

	public int maxPoolSize() {
		return maxThreads;
	}

	public int workerQueueSize() {
		return queue.size();
	}

	void putInQueue(Runnable r) {
		if (runCount == threads.size() && threads.size() < maxThreads) {
			PooledThread thread = new PooledThread();
			threads.add(thread);
			thread.start();
		}
		queue.addLast(r);
		queue.notify();
	}

	public void execute(Runnable r) {
		synchronized (queue) {
			putInQueue(r);
		}
	}

	private class PooledThread extends Thread {
		
		boolean running;

		private PooledThread() {
			running = false;
		}

		public void run() {
			while (true) {
				Runnable r;
				synchronized (queue) {
					while (queue.isEmpty()) {
						if (running) {
							runCount -= 1;
							running = false;
						}
						try {
							queue.wait();
						} catch (InterruptedException e) {
						}
					}
					if (!running) {
						runCount += 1;
						running = true;
					}
					r = queue.removeFirst();
				}
				try {
					r.run();
				} catch (RuntimeException e) {
					ThreadPool.log.error("线程池任务执行异常", e);
				}
			}
		}
	}

}